/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include<flash-ops.h>
#include<wifi-ops.h>
#include "keyboard.h"
#include "OLED.h"

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
struct usr_info{
	char usrname[16];
	char usrpasswo[16];
	char wifiname[16];
	char wifipasswo[16];
	int flag ;
};
struct usr_info msg;

char show2[25] ={0};
char show0[25] ={0};
char show1[25] ={0};
char show3[25] ={0};

char yf[] = {210,191,170,151,143,127,113,101,90,80,70,60,50,40};
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
xQueueHandle  queueKeyboard2TaskOledFlash;
xQueueHandle  queueBeepTaskHandle;

TaskHandle_t taskEspHandle;
TaskHandle_t taskOledHandle;
TaskHandle_t taskBeepHandle;
/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

RTC_HandleTypeDef hrtc;

TIM_HandleTypeDef htim4;

UART_HandleTypeDef huart1;
UART_HandleTypeDef huart3;

osThreadId defaultTaskHandle;
/* USER CODE BEGIN PV */
int __io_putchar(int ch)
{
	UBaseType_t vxx;
	vxx = portSET_INTERRUPT_MASK_FROM_ISR();
	HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,1);
	portCLEAR_INTERRUPT_MASK_FROM_ISR(vxx);
	return ch;
}

void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{
	printf("vApplicationStackOverflowHook detect %s stack overlay\r\n",pcTaskName);
}

void task_beep_fun(void *args)
{
	char val;

	while(1){
		//osDelay(100);	//in case of  many charator comes ...,sleep for
		BaseType_t rst = xQueueReceive(queueBeepTaskHandle,&val,portMAX_DELAY);
		if(rst == pdFALSE){
			continue;			//没有消息,就去刷新时间
		}

		printf("%s-%d got char %c\r\n",__func__,__LINE__,val);

		if( (val>='0') && (val <='9') ){
			HAL_TIM_PWM_Start (&htim4,TIM_CHANNEL_4);
			printf("%s-%d play %c\r\n",__func__,__LINE__,val);
			__HAL_TIM_SET_AUTORELOAD(&htim4, yf[val-'0']);
			__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,yf[val-'0']/2);
			osDelay(120);
			HAL_TIM_PWM_Stop (&htim4,TIM_CHANNEL_4);
		}
		/*charator # is no need ,becase  U V is incoming...*/
		if( (val == 'A') || (val == 'U') || (val == 'V')|| (val == '*')    ){
			HAL_TIM_PWM_Start (&htim4,TIM_CHANNEL_4);
			__HAL_TIM_SET_AUTORELOAD(&htim4, yf[ 7 ]);
			__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,yf[ 7 ]/2);
			osDelay(120);
			HAL_TIM_PWM_Stop (&htim4,TIM_CHANNEL_4);
		}
		if(val == 'D'){
			for(int i=0;i<8;i++){
				HAL_TIM_PWM_Start (&htim4,TIM_CHANNEL_4);
				__HAL_TIM_SET_AUTORELOAD(&htim4, yf[ i%2 ]);
				__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,yf[ i%2 ]/2);
				osDelay(200);
				HAL_TIM_PWM_Stop (&htim4,TIM_CHANNEL_4);
			}
		}
	}

}

int esp_ap_data_callback(char *data,int len)
{
	char *p;
		printf("ap get data \r\n");
		p = strstr(data,"username=");
		if(p){
			p+=strlen("username=");
			char recv_usrname[16]={0}; int i=0;
			while(p[i]!=',' && p[i]!= ';'){
				recv_usrname[i]=p[i];i++;
			}
			strcpy(msg.usrname,recv_usrname);
		}

		p=strstr(data,"password=");
		if(p){
		p+=strlen("password=");
		int i=0; char recv_password[16] = {0};
			while(p[i]!=',' && p[i]!=';'){
				recv_password[i] = p[i]; i++;
			}
			strcpy(msg.usrpasswo,recv_password);
		}

		p=strstr(data,"wifiname=");
			if(p){
			p+=strlen("wifiname=");
			int i=0; char recv_wifiname[16] = {0};
				while(p[i]!=',' && p[i]!=';'){
					recv_wifiname[i] = p[i]; i++;
				}
				strcpy(msg.wifiname,recv_wifiname);
		}

		p=strstr(data,"wifipassword=");
			if(p){
			p+=strlen("wifipassword=");
			int i=0; char recv_wifipasswo[32] = {0};
			while(p[i]!=',' && p[i]!=';'){
				recv_wifipasswo[i] = p[i]; i++;
			}
			strcpy(msg.wifipasswo,recv_wifipasswo);
		}
			p=strstr(data,"flag=");
					if(p){
					p+=strlen("flag=");
					int i=0; char recv_flag[16] = {0};
					while(p[i]!=',' && p[i]!=';'){
						recv_flag[i] = p[i]; i++;
					}
					int recvflag = atoi(recv_flag);
					msg.flag = recvflag;
				}
			printf("flag=%d\r\n",msg.flag);

			flash_ops_write(PAGE5_RCT6_ADDR, (int *)&msg, sizeof(msg));
			printf("reset\r\n");
			HAL_NVIC_SystemReset();
		return 0;
}

int esp_sta_data_callback(char *data,int len)
{
	printf("STA got data:%s\r\n",data);
	if( strstr(data,"time=")){
		RTC_DateTypeDef date;	RTC_TimeTypeDef time;	int year;
		sscanf(data,"toCli:Ur MSG GOT!time=20%d-%d-%d %d:%d:%d;",\
				&year,&date.Month,&date.Date,&time.Hours,&time.Minutes,&time.Seconds);
		date.Year=year-2000;
		printf("%s-%d got time 20%d-%d-%d %d:%d:%d\r\n",__func__,__LINE__, date.Year,date.Month,date.Date,time.Hours, time.Minutes, time.Seconds);
		HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN);
		HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN);
	}

	if(strstr(data,"MSG@")){
			//收到推送消息,处理中...
			if(strstr(data,"locked")){
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, 1);
			}else if(strstr(data,"unlock")){
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, 0);
			}
		}
	return 0;
}

void task_Esp_fun(void *args)
{
	int ret;
	flash_ops_read(PAGE5_RCT6_ADDR, &msg, sizeof(msg));

	esp_reset:
	if(msg.flag != 10086){
		snprintf(show2,sizeof(show2),"step in AP...  ");
		wifi_uart_prepare_idle(&huart3);
		ret = wifi_ap_init(&huart3,esp_ap_data_callback);
		if(ret<0){
			printf("%s-%d wifi_ap_init err,reset ######\r\n",__func__,__LINE__);
			goto esp_reset;
		}

		ret = wifi_ap_set_args(&huart3,"Lucy-AP","88888888");
		if(ret<0){
			printf("%s-%d wifi_ap_set_args err,reset ######\r\n",__func__,__LINE__);
			goto esp_reset;
		}
		snprintf(show2,sizeof(show2),"AP:SML_AP,88888888");

		int linkid = wifi_ap_tcp_listen_and_wait_connect_timeout(&huart3,9900,5*60*1000);
		if(linkid<0){
			printf("%s-%d wifi_ap_set_args err,reset ######\r\n",__func__,__LINE__);
			goto esp_reset;
		}
		while(1){
			osDelay(1000);
		}
	}else{
		snprintf(show2,sizeof(show2),"step into station...");
		wifi_uart_prepare_idle(&huart3);

		ret = wifi_station_init(&huart3,esp_sta_data_callback);
		if(ret<0){
			printf("%s-%d wifi_station_init err,reset ######\r\n",__func__,__LINE__);
			goto esp_reset;
		}

		ret = wifi_station_join_ap(&huart3,"oo00","12345678");
		//ret = wifi_station_join_ap(&huart3,msg.wifiname,msg.wifipasswo);
		if(ret<0){
			printf("%s-%d wifi_station_join_ap err,reset ######\r\n",__func__,__LINE__);
			goto esp_reset;
		}
		snprintf(show2,sizeof(show2),"Join wifi WANGX success");

		ret = wifi_station_tcp_connect(&huart3,"107.148.201.156",9900);
		if(ret<0){
			printf("%s-%d wifi_station_tcp_connect err,reset ######\r\n",__func__,__LINE__);
			goto esp_reset;
		}
		snprintf(show2,sizeof(show2),"connect Serv OK ...");

		char sendbuf[128];
		snprintf(sendbuf,sizeof(sendbuf),"toServ:action=log,usrname=%s,passwd=%s,devname=Joe;",msg.usrname,msg.usrpasswo);
		ret = wifi_station_tcp_send_data(&huart3,sendbuf,strlen(sendbuf));
		if(ret<0){
			printf("%s-%d wifi_station_tcp_send_data log send err\r\n",__func__,__LINE__);
			goto esp_reset;
		}

		snprintf(sendbuf,sizeof(sendbuf),"toServ:action=gettime;");
		ret = wifi_station_tcp_send_data(&huart3,sendbuf,strlen(sendbuf));
		if(ret<0){
			printf("%s-%d wifi_station_tcp_send_data gettime send err\r\n",__func__,__LINE__);
			goto esp_reset;
		}

		int err_cnt = 0;
		snprintf(sendbuf,sizeof(sendbuf),"toDev:devname=Lucy,v=%d alarm=%d;",3000,1);
		while(1){
			ret = wifi_station_tcp_send_data(&huart3,sendbuf,strlen(sendbuf));
			if(ret<0){
			printf("%s-%d wifi_station_tcp_send_data toDev err\r\n",__func__,__LINE__);
			err_cnt++;
			if(err_cnt>5){  printf("reset ######\r\n"); goto esp_reset;	 } else {  continue;  }
		}
			err_cnt=0;
		osDelay(5000);
	}


	}
}

void task_Oled_fun(void *pvParameters)
{
	BaseType_t rst;
	int show_stat = 0;
	char keynum;

	RTC_DateTypeDef date; RTC_TimeTypeDef time;

	char passwdbuf[10];
	char passwdchar[10];
	char pos = 0;

	while(1){

		if(show_stat == 0){

			HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
			HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
			snprintf(show0,sizeof(show0),"   Smart Lock  "); oled_show_fast(0, (uint8_t*)show0);

			snprintf(show1,sizeof(show1),"  %02d-%02d %02d:%02d:%02d",date.Month,date.Date,time.Hours,time.Minutes,time.Seconds);
			oled_show_fast( 16, (uint8_t*)show1);

			oled_show_fast(32,(uint8_t *)show2);
			osDelay(1000);
		}

		rst = xQueueReceive(queueKeyboard2TaskOledFlash,&keynum,100);
		if(rst == pdFALSE){
			continue;			//没有消息,就去刷新时间
		}
		printf("%s->%d recv keynum %c\r\n",__func__,__LINE__,keynum);
		show_stat = 1;

		if(keynum >= '0' && keynum <= '9' ){
			snprintf(show0,sizeof(show0),"   Password   ");	//定制 每行显示内容
			oled_show_fast(0,(uint8_t*)show0);
			passwdchar[pos] = '*';
			passwdbuf[pos] = keynum;
			pos++;
			snprintf(show1,sizeof(show1),"PASS:%s",passwdchar);
			oled_show_fast(16,(uint8_t*)"   ");		//clear line2,or show1 len is variable
			oled_show_fast(16,(uint8_t*)show1);
		}

		if(keynum == '*'){
			pos=0;
			memset(passwdbuf,0,sizeof(passwdbuf));
			memset(passwdchar,0,sizeof(passwdchar) );
			show_stat = 0;
			printf("%s->%d quit\n",__func__,__LINE__);
			continue;
		}
		if(keynum == '#' ||  pos == 6) {
					char notifyBeep;
					if( strncmp(passwdbuf,"123456",6) == 0 ){
						oled_show_fast(0, (uint8_t*)"                 ");
						oled_show_fast(0, (uint8_t*)" unlock success  ");

						//notify to beep
						notifyBeep = 'U';
						xQueueSendToBackFromISR(queueBeepTaskHandle,(void *)&notifyBeep,NULL);

						HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET);
						osDelay(2000);	//�??????????????????灯提醒延�??????????????????1sec
						HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET);
					}else {
						oled_show_fast(0, (uint8_t*)"                 ");
						oled_show_fast(0, (uint8_t*)" unlock failed   ");

						notifyBeep = 'V';
						xQueueSendToBackFromISR(queueBeepTaskHandle,(void *)&notifyBeep,NULL);

						HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET);
						osDelay(2000);	//�??????????????????灯提醒延�??????????????????1sec
						HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET);
					}


					/*还是恢复到以前的位置*/
					pos=0;				//清空all
					memset(passwdbuf,0,sizeof(passwdbuf));
					memset(passwdchar,0,sizeof(passwdchar) );
					show_stat = 0;		//�???????????????????始刷新时间去�???????????????????
				}

				if(keynum == 'A' ){
					printf("%s->%d step into AP\r\n",__func__,__LINE__);
					msg.flag=0;	//使之非法
					flash_ops_write(PAGE5_RCT6_ADDR,(int*)&msg,sizeof(msg));
					HAL_NVIC_SystemReset(); 		//chongqi

				}
	}
}

void HAL_GPIO_EXTI_Callback (uint16_t  GPIO_Pin)
{
	static int pre_ticks = 0;

	int cur_ticks = HAL_GetTick();
	if(cur_ticks-pre_ticks <300){
		return;
	}
	pre_ticks = cur_ticks;

	char keynum = keyboard_getKeyNum(GPIO_Pin);

	//printf("%s-%d %c\r\n",__func__,__LINE__,keynum);
	xQueueSendToBackFromISR(queueKeyboard2TaskOledFlash,(void *)&keynum,NULL);
	xQueueSendToBackFromISR(queueBeepTaskHandle,(void *)&keynum,NULL);
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	//other thing to do
	wifi_uart_prepare_idle(huart);	//after recv success, wo must prepare uart for next time
}
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_I2C1_Init(void);
static void MX_RTC_Init(void);
static void MX_TIM4_Init(void);
void StartDefaultTask(void const * argument);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  MX_I2C1_Init();
  MX_RTC_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */


  keyboard_init();

  OLED_init() ;
  //OLED_flash();
  OLED_clear();

  RTC_DateTypeDef date; RTC_TimeTypeDef time;
   date.Year=24;date.Month=3;date.Date=29;
   time.Hours=10;time.Minutes=46;time.Seconds=00;
   HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN);
   HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN);
  /* USER CODE END 2 */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  queueKeyboard2TaskOledFlash = xQueueCreate(1,sizeof(char));
    if(queueKeyboard2TaskOledFlash == NULL){
  	  printf("que keybaord err\r\n"); return -23;
    }

    queueBeepTaskHandle = xQueueCreate(1,sizeof(char));
      if(queueBeepTaskHandle == NULL){
    	  printf("que beep err\r\n"); return -23;
      }

    BaseType_t rst = xTaskCreate(task_Oled_fun,"taskOled",128*2,NULL,osPriorityHigh,&taskOledHandle );
      if(rst == pdFALSE){
        	  printf("xTaskCreate taskespoled err\r\n"); return -23;
          }

      rst = xTaskCreate(task_Esp_fun,"taskEsp",128*3,NULL,osPriorityHigh,&taskEspHandle );
        if(rst == pdFALSE){
          	  printf("xTaskCreate taskespoled err\r\n"); return -23;
            }

        rst = xTaskCreate(	task_beep_fun,"taskBeep",
            		128*3,NULL,osPriorityHigh, &taskBeepHandle   );
              if(rst == pdFALSE){
            	  printf("xTaskCreate taskbeep err\r\n"); return -23;
              }

  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of defaultTask */
  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */





  /* USER CODE END RTOS_THREADS */

  /* Start scheduler */
  osKernelStart();

  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL8;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
  PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief RTC Initialization Function
  * @param None
  * @retval None
  */
static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef DateToUpdate = {0};

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */
  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
  hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */

  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0x0;
  sTime.Minutes = 0x0;
  sTime.Seconds = 0x0;

  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;
  DateToUpdate.Month = RTC_MONTH_JANUARY;
  DateToUpdate.Date = 0x1;
  DateToUpdate.Year = 0x0;

  if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

/**
  * @brief TIM4 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM4_Init(void)
{

  /* USER CODE BEGIN TIM4_Init 0 */

  /* USER CODE END TIM4_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM4_Init 1 */

  /* USER CODE END TIM4_Init 1 */
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 640-1;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 65535;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM4_Init 2 */

  /* USER CODE END TIM4_Init 2 */
  HAL_TIM_MspPostInit(&htim4);

}

/**
  * @brief USART1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART1_UART_Init(void)
{

  /* USER CODE BEGIN USART1_Init 0 */

  /* USER CODE END USART1_Init 0 */

  /* USER CODE BEGIN USART1_Init 1 */

  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */

  /* USER CODE END USART1_Init 2 */

}

/**
  * @brief USART3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART3_UART_Init(void)
{

  /* USER CODE BEGIN USART3_Init 0 */

  /* USER CODE END USART3_Init 0 */

  /* USER CODE BEGIN USART3_Init 1 */

  /* USER CODE END USART3_Init 1 */
  huart3.Instance = USART3;
  huart3.Init.BaudRate = 115200;
  huart3.Init.WordLength = UART_WORDLENGTH_8B;
  huart3.Init.StopBits = UART_STOPBITS_1;
  huart3.Init.Parity = UART_PARITY_NONE;
  huart3.Init.Mode = UART_MODE_TX_RX;
  huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART3_Init 2 */

  /* USER CODE END USART3_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8, GPIO_PIN_RESET);

  /*Configure GPIO pins : PA0 PA1 PA2 PA3 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PA4 PA5 PA6 PA7 */
  GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PC6 PC7 PC8 */
  GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI4_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(EXTI4_IRQn);

  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END 5 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

